package com.am.server.api.system.log.aspect.service.impl;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.am.server.api.system.log.aspect.annotation.WriteLog;
import com.am.server.api.system.log.aspect.service.ProcessLogService;
import com.am.server.api.system.log.model.dto.SaveLogDto;
import com.am.server.api.system.log.model.entity.DefaultLogExtendEntity;
import com.am.server.api.system.log.service.LogService;
import com.am.server.api.system.user.dao.rdb.AdminUserDao;
import com.am.server.api.system.user.exception.UserNotExistException;
import com.am.server.api.system.user.model.entity.AdminUserEntity;
import com.am.server.common.base.service.CommonService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Optional;

/**
 * 默认处理日志实现
 *
 * @author 阮雪峰
 */
@Service
public class DefaultProcessLogServiceImpl implements ProcessLogService {

    private final AdminUserDao adminUserDAO;

    private final LogService logService;

    private final CommonService commonService;

    private final HttpServletRequest request;

    public DefaultProcessLogServiceImpl(AdminUserDao adminUserDAO, LogService logService, CommonService commonService, HttpServletRequest request) {
        this.adminUserDAO = adminUserDAO;
        this.logService = logService;
        this.commonService = commonService;
        this.request = request;
    }

    @Override
    public void process(Class<?> targetClass, WriteLog targetClassWriteLog, Method targetMethod, WriteLog targetMethodWriteLog, JoinPoint joinPoint) {
        String name;
        if (commonService.isSupperUser()) {
            name = "超级管理员";
        } else {
            name = adminUserDAO.findById(commonService.getLoginUserId())
                    .map(AdminUserEntity::getUsername)
                    .orElseThrow(UserNotExistException::new);
        }
        String parameterJsonContent = getParameterJsonContent(joinPoint);
        SaveLogDto log = new SaveLogDto()
                .setMenu(Optional.ofNullable(targetClassWriteLog).map(WriteLog::value).orElse(""))
                .setOperate(Optional.ofNullable(targetMethodWriteLog).map(WriteLog::value).orElse(""))
                .setName(name)
                .setIp(ServletUtil.getClientIP(request))
                .setExtend(new DefaultLogExtendEntity(parameterJsonContent));

        logService.save(log);
    }

    private String getParameterJsonContent(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String[] parameterNames = signature.getParameterNames();
        JSONObject jsonObject = new JSONObject();
        int index = 0;
        for (Object arg : joinPoint.getArgs()) {
            jsonObject.putOpt(parameterNames[index], JSONUtil.parseObj(arg));
            index++;
        }
        return jsonObject.toString();
    }
}
